package com.molichuxing.gateway.bff.dealer.services.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import com.google.gson.JsonObject;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.gateway.bff.dealer.entity.request.create.DealerEsignCreateVo;
import com.molichuxing.services.infrastructure.dto.response.response.AccountDto;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.SystemTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.molichuxing.framework.contants.RedisKeyConst;
import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.dto.TabDto;
import com.molichuxing.framework.utils.RedisUtil;
import com.molichuxing.gateway.bff.dealer.convertor.Convert;
import com.molichuxing.gateway.bff.dealer.entity.request.create.DealerCreateVo;
import com.molichuxing.gateway.bff.dealer.entity.request.modify.DealerModifyStatusVo;
import com.molichuxing.gateway.bff.dealer.entity.request.modify.DealerModifyVo;
import com.molichuxing.gateway.bff.dealer.entity.response.DealerEsignInfoVo;
import com.molichuxing.gateway.bff.dealer.entity.response.DealerInfoVo;
import com.molichuxing.gateway.bff.dealer.entity.response.DealerListVo;
import com.molichuxing.gateway.bff.dealer.entity.response.DealerProvinceVo;
import com.molichuxing.gateway.bff.dealer.entity.response.DealerStoreVo;
import com.molichuxing.gateway.bff.dealer.entity.response.DealerVo;
import com.molichuxing.gateway.bff.dealer.services.DealerBffService;
import com.molichuxing.gateway.property.DealerStatusEnum;
import com.molichuxing.gateway.property.EmailSubjectEnum;
import com.molichuxing.gateway.property.SystemNameEnum;
import com.molichuxing.gateway.utils.OpEmailUtil;
import com.molichuxing.gateway.utils.TokenUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;
import com.molichuxing.services.business.dto.request.CreateDealerSuperAccountDto;
import com.molichuxing.services.business.dto.request.UpdateDealerSuperAccountDto;
import com.molichuxing.services.business.dto.request.create.DealerBizCreateDto;
import com.molichuxing.services.business.dto.request.create.EsignDealerBizCreateDto;
import com.molichuxing.services.business.dto.request.modify.DealerBizModifyDto;
import com.molichuxing.services.business.dto.response.DealerBizDto;
import com.molichuxing.services.business.dto.response.DealerDetailInfoBizDto;
import com.molichuxing.services.business.dto.response.DealerInfoBizDto;
import com.molichuxing.services.business.dto.response.DealerStoreBizDto;
import com.molichuxing.services.business.service.AccountBizService;
import com.molichuxing.services.business.service.DealerBizService;
import com.molichuxing.services.business.service.EsignBizService;
import com.molichuxing.services.business.service.GoodsBizService;
import com.molichuxing.services.business.service.SmsBizService;
import com.molichuxing.services.infrastructure.dto.response.DealerDetailDto;
import com.molichuxing.services.infrastructure.dto.response.DealerDto;
import com.molichuxing.services.infrastructure.dto.response.EsignDealerDto;
import com.molichuxing.services.infrastructure.dto.response.RegionInfoDto;
import com.molichuxing.services.infrastructure.dto.response.SubcompanyDto;
import com.molichuxing.services.property.GoodsForbidSaleEnum;
import com.molichuxing.services.property.SmsTemplateEnum;
import springfox.documentation.spring.web.json.Json;

/**
 * 经销商信息相关bff
 *
 * @author zhaopenghui
 * @date 2019年8月26日
 */
@Service("dealerBffService")
public class DealerBffServiceImpl implements DealerBffService {
    private static final Logger logger = LoggerFactory.getLogger(DealerBffServiceImpl.class);

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private DealerBizService dealerBizService;
    @Resource
    private DealerService dealerService;
    @Resource
    private DealerDetailService dealerDetailService;
    @Resource
    private RegionService regionService;
    @Resource
    private EsignBizService esignBizService;
    @Resource
    private EsignDealerService esignDealerService;
    @Resource
    private SubcompanyService subcompanyService;
    @Resource
    GoodsBizService goodsBizService;
    @Resource
    AccountBizService accountBizService;
    @Resource
    AccountService accountService;
    @Resource
    private OpEmailUtil emailUtil;
    @Resource
    private SmsBizService smsBizService;
    @Resource
    private TokenUtil tokenUtil;
    @Value("${password.salt}")
    private String PASSWORD_SALT;

    /**
     * 经销商分页列表
     *
     * @param params
     * @param pageNum
     * @param pageSize
     * @return
     * @throws Exception
     */
    @Override
    public Paged<DealerListVo> getDealerPage(Map<String, Object> params, Integer pageNum, Integer pageSize) throws Exception {
        Paged<DealerBizDto> dealerPage = dealerBizService.getDealerPage(params, pageNum, pageSize);
        List<DealerBizDto> dealerBizDtoList = dealerPage.getList();
        if (null == dealerBizDtoList) {
            Paged<DealerListVo> paged = new Paged<DealerListVo>();
            return getPageTab(paged);
        }

        List<Integer> regionIdList = new ArrayList<>();
        for (DealerBizDto dealerBizDto : dealerBizDtoList) {
            Integer regionId = dealerBizDto.getRegionId();
            regionIdList.add(regionId);
        }

        Map<Integer, RegionInfoDto> regionInfoMap = regionService.getRegionInfoListByIds(regionIdList);
        List<DealerListVo> dealerVoList = Convert.toDealerListVoList(dealerBizDtoList, regionInfoMap);

        Paged<DealerListVo> paged = new Paged<DealerListVo>(dealerVoList, dealerPage.getTotal(), pageSize);
        return getPageTab(paged);
    }

    /**
     * 获取分页tab值
     *
     * @return
     * @throws Exception
     */
    private Paged<DealerListVo> getPageTab(Paged<DealerListVo> paged) throws Exception {
        Map<Integer, Integer> statusCountMap = dealerService.getDealerCountByStatus();
        Integer allCount = dealerService.getCount();
        List<TabDto> tabList = new ArrayList<>();
        for (DealerStatusEnum dealerStatusEnum : DealerStatusEnum.values()) {
            int value = dealerStatusEnum.getValue();
            String name = dealerStatusEnum.getName();
            Integer count = 0;
            if (DealerStatusEnum.ALL.getValue() == value) {
                count = allCount;
            } else if (null != statusCountMap && statusCountMap.size() > 0) {
                count = statusCountMap.get(value);
            }

            if (null == count) {
                count = 0;
            }

            TabDto tabDto = new TabDto();
            tabDto.setName(name);
            tabDto.setType(value);
            tabDto.setCount(count);
            tabList.add(tabDto);
        }

        return paged.setTab(tabList);
    }

    /**
     * 详情-获取经销商基础信息
     *
     * @param dealerId
     * @return
     * @throws Exception
     */
    @Override
    public DealerInfoVo getDealerInfo(Integer dealerId) throws Exception {
        DealerInfoBizDto dealerInfoBizDto = dealerBizService.getDealerInfo(dealerId);
        DealerDetailInfoBizDto dealerDetailInfoBizDto = dealerBizService.getDealerDetailInfo(dealerId);
        DealerInfoVo dealerInfoVo = Convert.toDealerInfoVo(dealerInfoBizDto);
        Integer subcompanyId = dealerDetailInfoBizDto.getSubcompanyId();
        SubcompanyDto subcompanyDto = subcompanyService.getSubcompanyNameById(subcompanyId);
        if (subcompanyDto != null) {
            dealerInfoVo.setSubcompanyName(subcompanyDto.getFullName());
        }

        DealerInfoVo dealerInfo = Convert.toDealerInfoVo(dealerDetailInfoBizDto, dealerInfoVo);
        Integer regionId = dealerInfoBizDto.getRegionId();
        String address = dealerDetailInfoBizDto.getAddress();
        getRegionAddress(regionId, address, dealerInfo);
        return dealerInfo;
    }

    /**
     * 获取地址
     *
     * @param regionId
     * @return
     */
    private void getRegionAddress(Integer regionId, String address, DealerInfoVo dealerInfo) throws Exception {
        if (null == regionId) {
            return;
        }

        RegionInfoDto regionInfoDto = regionService.getCityNameByCityId(regionId);
        if (null == regionInfoDto) {
            return;
        }

        String returnStr = "";
        String provinceName = regionInfoDto.getProvinceFullName();
        String cityName = regionInfoDto.getCityFullName();
        Integer provinceId = regionInfoDto.getProvinceId();
        dealerInfo.setProvinceId(provinceId);
        dealerInfo.setProvinceName(provinceName);
        dealerInfo.setCityName(cityName);
        if (StringUtils.isNotBlank(provinceName)) {
            returnStr = returnStr + provinceName;
        }
        if (StringUtils.isNotBlank(cityName)) {
            returnStr = returnStr + cityName;
        }

        if (StringUtils.isNotBlank(returnStr)) {
            dealerInfo.setDetailAddress(returnStr + address);
        }
    }

    /**
     * 详情-电子章
     *
     * @param dealerId
     * @return
     * @throws Exception
     */
    @Override
    public DealerEsignInfoVo getDealerEsignInfoVo(Integer dealerId) throws Exception {
        DealerDetailInfoBizDto dealerDetailInfoBizDto = dealerBizService.getDealerDetailInfo(dealerId);
        DealerEsignInfoVo dealerEsignInfoVo = Convert.toDealerEsignInfoVo(dealerDetailInfoBizDto);

        EsignDealerDto esignDealerDto = esignDealerService.getEsignDealerById(dealerId);
        if (esignDealerDto != null) {
            String sealData = esignDealerDto.getSealData();
            dealerEsignInfoVo.setEsignBase64(sealData);
        }
        return dealerEsignInfoVo;
    }

    /**
     * 编辑经销商信息
     *
     * @param dealerModifyVo
     * @return
     * @throws Exception
     */
    @Override
    public Boolean modifyDealer(DealerModifyVo dealerModifyVo) throws Exception {
        String email = dealerModifyVo.getEmail();
        Integer dealerId = dealerModifyVo.getDealerId();

        AccountDto accountDto = accountBizService.getAccountByDealer(email);
        if (accountDto != null && !dealerId.equals(accountDto.getDealerId())) {
            throw new BizException("邮箱已存在");
        }

        DealerDetailDto dealerDetailDto = dealerDetailService.getDealerDetailById(dealerId);

        DealerBizModifyDto dealerBizModifyDto = Convert.toDealerBizModifyDto(dealerModifyVo);
        Boolean modifyDealerBoolean = dealerBizService.modifyDealer(dealerBizModifyDto);
        if (!modifyDealerBoolean) {
            return false;
        }

        EsignDealerBizCreateDto esignDealerBizCreateDto = new EsignDealerBizCreateDto();
        BeanUtils.copyProperties(dealerModifyVo, esignDealerBizCreateDto);
        createEsignDealer(esignDealerBizCreateDto);

        String oldEmail = dealerDetailDto.getEmail();
        if (!email.trim().equals(oldEmail)) {
            String phone = dealerModifyVo.getResponsiblePhone();
            String name = dealerModifyVo.getShortName();
            String password = modifyDealerSuperAccount(dealerModifyVo, dealerId);
            modifyDealerSendMessage(email, password, phone, name);
        }
        return true;
    }

    /**
     * 修改，系统自动生成超级管理员帐号
     *
     * @param dealerModifyVo
     * @param dealerId
     * @return
     * @throws Exception
     */
    private String modifyDealerSuperAccount(DealerModifyVo dealerModifyVo, Integer dealerId) throws Exception {
        String email = dealerModifyVo.getEmail();
        String shortName = dealerModifyVo.getShortName();
        String responsiblePhone = dealerModifyVo.getResponsiblePhone();

        UpdateDealerSuperAccountDto updateDealerSuperAccountDto = new UpdateDealerSuperAccountDto();
        updateDealerSuperAccountDto.setId(dealerId);
        updateDealerSuperAccountDto.setEmail(email);
        updateDealerSuperAccountDto.setDealerName(shortName);
        updateDealerSuperAccountDto.setUserPhone(responsiblePhone);
        updateDealerSuperAccountDto.setPasswordSalt(PASSWORD_SALT);
        return accountBizService.updateDealerSuperAccount(updateDealerSuperAccountDto);
    }

    /**
     * 编辑经销商营业状态
     *
     * @param dealerBizModifyStatusVo
     * @return
     * @throws Exception
     */
    @Override
    public Boolean modifyDealerStatus(DealerModifyStatusVo dealerBizModifyStatusVo) throws Exception {
        Integer dealerId = dealerBizModifyStatusVo.getDealerId();
        Integer status = dealerBizModifyStatusVo.getStatus();

        Boolean modifyBoolean = dealerBizService.modifyDealerStatus(dealerId, status);
        if (!modifyBoolean) {
            return false;
        }

        if (DealerStatusEnum.CLOSE.getValue() == status) {
            Boolean goodsBoolean = goodsBizService.settingGoodsSaleByDealer(dealerId, GoodsForbidSaleEnum.NO);
            if (!goodsBoolean) {
                return false;
            }

            boolean accountBoolean = accountBizService.modifyAccountToDisableByDealerId(dealerId);
            if (!accountBoolean) {
                return false;
            }
        }

        return true;
    }

    /**
     * 添加经销商
     *
     * @param dealerCreateVo
     * @return
     * @throws Exception
     */
    @Override
    public Boolean createDealer(DealerCreateVo dealerCreateVo) throws Exception {
        String email = dealerCreateVo.getEmail();
        AccountDto account = accountService.getAccount(email, SystemTypeEnum.DEALER.getValue());
        if (account != null) {
            throw new BizException("邮箱已存在");
        }

        DealerBizCreateDto dealerBizCreateDto = Convert.toDealerBizCreateDto(dealerCreateVo);
        Integer dealerId = dealerBizService.createDealer(dealerBizCreateDto);

        EsignDealerBizCreateDto esignDealerBizCreateDto = new EsignDealerBizCreateDto();
        BeanUtils.copyProperties(dealerCreateVo, esignDealerBizCreateDto);
        esignDealerBizCreateDto.setDealerId(dealerId);
        createEsignDealer(esignDealerBizCreateDto);

        String password = createDealerSuperAccount(dealerCreateVo, dealerId);
        createDealerSendMessage(dealerCreateVo, password);
        return true;
    }

    /**
     * 系统自动生成超级管理员帐号
     *
     * @param dealerCreateVo
     * @param dealerId
     * @return
     */
    private String createDealerSuperAccount(DealerCreateVo dealerCreateVo, Integer dealerId) throws Exception {
        String shortName = dealerCreateVo.getShortName();
        String email = dealerCreateVo.getEmail();
        String responsiblePhone = dealerCreateVo.getResponsiblePhone();

        CreateDealerSuperAccountDto createDealerSuperAccountDto = new CreateDealerSuperAccountDto();
        createDealerSuperAccountDto.setDealerId(dealerId);
        createDealerSuperAccountDto.setDealerName(shortName);
        createDealerSuperAccountDto.setDealerEmail(email);
        createDealerSuperAccountDto.setUserPhone(responsiblePhone);
        createDealerSuperAccountDto.setPasswordSalt(PASSWORD_SALT);
        return accountBizService.createDealerSuperAccount(createDealerSuperAccountDto);
    }

    /**
     * 添加发送消息
     *
     * @param dealerCreateVo
     * @param password
     * @return
     * @throws Exception
     */
    private Boolean createDealerSendMessage(DealerCreateVo dealerCreateVo, String password) throws Exception {
        String email = dealerCreateVo.getEmail();
        String phone = dealerCreateVo.getResponsiblePhone();
        String name = dealerCreateVo.getShortName();

        int smsTemplateValue = SmsTemplateEnum.CREATE_DEALER_ACCOUNT_SUCCESS.getValue();
        return sendEmailAndSms(email, password, phone, name, smsTemplateValue, null);
    }

    /**
     * 修改发送消息
     *
     * @param account
     * @param password
     * @param phone
     * @param name
     * @return
     * @throws Exception
     */
    private Boolean modifyDealerSendMessage(String account, String password, String phone, String name) throws Exception {
        int smsTemplateValue = SmsTemplateEnum.MODIFY_DEALER_ACCOUNT_SUCCESS.getValue();
        JSONObject json = new JSONObject();
        json.put("useremail", account);
        String paramJson = json.toJSONString();
        return sendEmailAndSms(account, password, phone, name, smsTemplateValue, paramJson);
    }


    /**
     * 发送消息
     *
     * @param account
     * @param password
     * @param phone
     * @param name
     * @return
     */
    private Boolean sendEmailAndSms(String account, String password, String phone, String name, int smsTemplateValue, String paramJson) throws Exception {
        UserEntity currentLoginUser = tokenUtil.getUser();
        String emailContent = emailUtil.editorCreateDealerAccountSuccessContent(account, password);
        boolean sendResult = emailUtil.send(EmailSubjectEnum.CREATE_DEALER_ACCOUNT_SUCCESS.getName(), emailContent, account);
        if (!sendResult) {
            String errorEmailContent = emailUtil.editorCreateAccountErrorContent(SystemNameEnum.DEALER, name);
            return emailUtil.send(name + EmailSubjectEnum.CREATE_ACCOUNT_ERROR.getName(), errorEmailContent, currentLoginUser.getAccount());
        } else {
            return smsBizService.sendMessage(phone, smsTemplateValue, paramJson, null); //发送短信
        }
    }


    /**
     * 添加印章
     *
     * @param esignDealerBizCreateDto
     * @return
     * @throws Exception
     */
    private Boolean createEsignDealer(EsignDealerBizCreateDto esignDealerBizCreateDto) throws Exception {
        return esignBizService.createEsignDealer(esignDealerBizCreateDto);
    }

    /**
     * 添加印章
     *
     * @param list
     * @return
     * @throws Exception
     */
    private Boolean createEsignDealer(List<EsignDealerBizCreateDto> list) throws Exception {
        return esignBizService.createEsignDealer(list);
    }

    /**
     * 经销商门店联动
     *
     * @return
     * @throws Exception
     */
    @Override
    public List<DealerStoreVo> getDealerStore(Integer status, Integer type, Integer dealerId, Boolean dealerIsShow) throws Exception {
        List<DealerStoreBizDto> dealerStoreList = dealerBizService.getDealerStore(status, type, dealerId, dealerIsShow);
        return Convert.toDealerStoreVoList(dealerStoreList);
    }

    /**
     * 经销商列表
     *
     * @return
     * @throws Exception
     */
    @Override
    public List<DealerVo> getDealerList() throws Exception {
        List<DealerDto> dealerDtoList = dealerService.getDealerList();
        return Convert.toDealerVo(dealerDtoList);
    }

    /**
     * 查询所有存在经销商的省份信息
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<DealerProvinceVo> getDealerProvince() {
        List<DealerProvinceVo> result = null;
        // redis中获取
        String dealerProvinces = redisUtil.get(RedisKeyConst.DEALER_PROVINCE);
        if (StringUtils.isNotBlank(dealerProvinces)) {
            // 存在
            return JSONObject.parseObject(dealerProvinces, List.class);
        }
        List<Integer> regionIds = dealerService.getRegionId();
        if (regionIds == null || regionIds.isEmpty()) {
            return result;
        }
        // 根据市id查询省信息
        List<RegionInfoDto> regions = regionService.getProvincesByCityIds(regionIds);
        if (regions == null || regions.isEmpty()) {
            return result;
        }
        result = Convert.toDealerProvinceVo(regions);
        // 存入redis
        redisUtil.set(RedisKeyConst.DEALER_PROVINCE, JSONObject.toJSONString(result));
        return result;
    }

    /**
     * 查询经销商基本信息
     *
     * @param provinceId 省id
     * @return
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<DealerVo> getDealer(Integer provinceId) {
        List<DealerVo> result = null;
        // redis中获取
        // String redisKey = RedisKeyConst.DEALER_PROVINCE_DEALER + provinceId;
        // String dealers = redisUtil.get(redisKey);
        // if (StringUtils.isNotBlank(dealers)) {
        // // 存在
        // return JSONObject.parseObject(dealers, List.class);
        // }

        // 根据省id查询出所有市id
        List<Integer> cityIds = regionService.getCityIdsByProvinceId(provinceId);
        if (cityIds == null || cityIds.isEmpty()) {
            return result;
        }
        // 根据市id查询所有经销商信息
        List<DealerDto> dealerDtos = dealerService.getDealerByRegionId(cityIds);
        if (dealerDtos == null || dealerDtos.isEmpty()) {
            return result;
        }
        result = Convert.toDealerVo(dealerDtos);
        // 存入redis
        // redisUtil.set(redisKey, JSONObject.toJSONString(result));
        return result;
    }

    /**
     * 创建经销商印章
     *
     * @param list
     * @return
     * @throws Exception
     */
    @Override
    public Boolean createDealerEsign(List<DealerEsignCreateVo> list) throws Exception {
        if (list != null && list.size() > 0) {
            List<EsignDealerBizCreateDto> esignDealerBizCreateDtoList = Convert.toEsignDealerBizCreateDtoList(list);
            return createEsignDealer(esignDealerBizCreateDtoList);
        } else {
            List<DealerDto> allDealerList = dealerService.getAllDealerList(null, null, null);
            if (null == allDealerList || allDealerList.size() < 1) {
                throw new BizException("经销商不存在");
            }

            List<Integer> dealerIdList = new ArrayList<>();
            for (DealerDto dealerDto : allDealerList) {
                Integer dealerId = dealerDto.getDealerId();
                dealerIdList.add(dealerId);
            }

            List<DealerDetailDto> dealerDetailList = dealerDetailService.getDealerDetailListByIds(dealerIdList);
            if (null == dealerDetailList || dealerDetailList.size() < 1) {
                throw new BizException("经销商不存在");
            }

            Map<Integer, EsignDealerDto> esignDealerMap = esignDealerService.getEsignDealerMap();
            if (null == esignDealerMap || esignDealerMap.size() < 1) {
                List<EsignDealerBizCreateDto> esignDealerBizCreateDtoList = Convert.toEsignDealerBizCreateList(dealerDetailList);
                return createEsignDealer(esignDealerBizCreateDtoList);
            }

            List<DealerDetailDto> dealerList = new ArrayList<>();
            for (DealerDetailDto dealerDetailDto : dealerDetailList) {
                Integer dealerId = dealerDetailDto.getDealerId();
                String horizontalText = dealerDetailDto.getHorizontalText();
                String upperChord = dealerDetailDto.getUpperChord();
                String bottomChord = dealerDetailDto.getBottomChord();
                if (null == dealerId) {
                    continue;
                }
                if (StringUtils.isBlank(horizontalText) && StringUtils.isBlank(upperChord) && StringUtils.isBlank(bottomChord)) {
                    continue;
                }

                EsignDealerDto esignDealerDto = esignDealerMap.get(dealerId);
                if (null == esignDealerDto) {
                    dealerList.add(dealerDetailDto);
                    continue;
                }

                String sealData = esignDealerDto.getSealData();
                if (StringUtils.isBlank(sealData)) {
                    dealerList.add(dealerDetailDto);
                }
            }

            List<EsignDealerBizCreateDto> esignDealerBizCreateDtoList = Convert.toEsignDealerBizCreateList(dealerList);
            return createEsignDealer(esignDealerBizCreateDtoList);
        }
    }

    @Override
    public List<DealerVo> getDealerListByParam(Map<String, Object> param) {
        List<DealerDto> dealerDtoList = dealerService.getDealerListByParam(param);
        return Convert.toDealerVo(dealerDtoList);
    }

    @Override
    public List<DealerVo> getDealerByShortNameFuzzy(String dealerName,Integer status, Integer type) {
        List<DealerDto> dealerDtoList = dealerService.getDealerByShortNameFuzzy(dealerName,status,type);
        return Convert.toDealerVo(dealerDtoList);
    }

}
